#ifndef _PROTOCAL_H
#define _PROTOCAL_H

#define COMM_SEND_BUF_SIZE        (60)
#define COMM_RECV_BUF_SIZE        (60)

/* Rinnai transmit command */
#define TEXT_SET          0x53
#define TEXT_GET          0x47
#define TEXT_RES          0x52
#define TEXT_INF          0x49
#define TEXT_ACK          0x41
#define TEXT_NAK          0x4E
 
#define IsCommandValid(cmd)  (cmd == TEXT_SET || cmd == TEXT_GET || cmd == TEXT_RES || cmd == TEXT_INF || cmd == TEXT_ACK || cmd == TEXT_NAK)
#define ResetRecvFsm(com)     do{com->RecvIndex = 0;  com->RecvSm  = SM_RECV_STX; }while(0)
			                                         

#define COMM_PACKAGE_SIZE         (6)
#define PACK_SIZE_OFFSET          (2)   /* 通信包中长度的偏移 */
#define PACK_CMD_OFFSET           (3)   /* 通信包中命令的偏移 */
#define PACK_DATA_OFFSET          (4)   /* 通信包中数据的偏移 */

#define RETRY_COUNT_MAX           (3)
#define ACK_TIMEOUT               (20)   /* 100MS */

#define F2_DATA_SIZE     (2+18)
#define F2_SIZE          (F2_DATA_SIZE + COMM_PACKAGE_SIZE)
#define F0_DATA_SIZE     (2+21)
#define F0_SIZE          (F0_DATA_SIZE + COMM_PACKAGE_SIZE)
#define F1_WIFI_DATA_SIZE     (2+28)
#define F1_MAIN_DATA_SIZE     (2+22)


/* 電文番号1 */
enum{
   CMD_F0      =  0xF0,
   CMD_F2      =  0xF2,  
};

typedef enum 
{  SEND_STA_IDLE,
   SEND_STA_START,
   SEND_STA_RUN,
}sendState_t;

typedef enum{
   SM_SEND_IDLE,
   SM_SEND_START,
   SM_SEND_END,
   SM_SEND_ACK,
   SM_SEND_FINISH,

}sendSm_t;

#define PACK_STX     0x02
#define PACK_SORT    0x09
#define PACK_ETX     0x03

#define SEND_TIMEOUT    10  /* TODO: */

typedef enum{
   SM_RECV_STX  = 0,
   SM_RECV_SORT,
   SM_RECV_LENGTH,
   SM_RECV_COMMAND,
   SM_RECV_TEXT,
   SM_RECV_ETX,
   SM_RECV_BCC,
}commState_t;

typedef struct _CommStru
{
   sendState_t    SendState;
   commState_t    RecvSm;
   sendSm_t       Sm; 
   uint8_t        RetryCount;         /* 通信失败重发计数 */
   uint8_t        DisableRetry;       /* 临时关闭重发，下次通信会自动开启 */
   uint8_t        Timeout;            /* 超时, 单位时10ms */
   uint8_t        SendIndex;          /* 发送索引 */
   uint8_t        SendLen;
   uint8_t        bSendFinish;
   uint8_t        recv_len;
   uint8_t        RecvIndex;
   uint8_t        DataLength;         /* 数据区长度 */
   uint8_t        send_buf[COMM_SEND_BUF_SIZE];
   uint8_t        RecvBuffTemp[COMM_RECV_BUF_SIZE]; /* 接收数据临时保存区 */
   uint8_t        RecvBuff[COMM_RECV_BUF_SIZE]; 
   void          (*ReceiveFunc)(struct _CommStru *com);
   void          (*PhySendByte)(uint8_t dat);
}Comm_t;

#define GetRecvBuff(com)   com->RecvBuff+PACK_DATA_OFFSET
#define GetSendBuff(com)   com->send_buf+PACK_DATA_OFFSET

#define GetCmd(buf)        buf[PACK_DATA_OFFSET]
#define GetSubCmd(buf)         buf[PACK_DATA_OFFSET+1]

uint8_t checksum(uint8_t *buf,uint8_t size);
void COM_SendACK(Comm_t *com);
void COM_SendNAK(Comm_t *com);
void COM_Send(Comm_t *com, uint8_t cmd, uint8_t len);
void COM_Init(Comm_t *com);
void COM_Fsm(Comm_t *com);

uint8_t COM_IsBusy(Comm_t *com);
/** @brief 关闭重发，待本次通信完成后自动打开重发 */
void COM_DisableRetry(Comm_t *com);

#endif
